非阻塞式socket建立以及如何判断对方断开 |
您所在的位置:网站首页 › socket c语言 服务端 判断客户端断开 › 非阻塞式socket建立以及如何判断对方断开 |
最近写的程序要求的是在控制线程中使用非阻塞的socket,以前没怎么接触过,先贴出代码如下: #define sockopt_noblock(socket, noblock) do{\ int val = (noblock);\ ioctl((socket), FIONBIO, (int)&val);\ } while(0) int conn_nonb(int sockfd, const struct sockaddr_in *saptr, socklen_t salen, int nsec) { int flags, n, error, code; socklen_t len; fd_set wset; struct timeval tval; flags = fcntl(sockfd, F_GETFL, 0); fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); sockopt_noblock(sockfd, 1); error = 0; if ((n == connect(sockfd, (struct sockaddr *)saptr, salen)) == 0) { goto done; } else if (n < 0 && errno != EINPROGRESS){ return RS_ERROR; } /* Do whatever we want while the connect is taking place */ FD_ZERO(&wset); FD_SET(sockfd, &wset); tval.tv_sec = nsec; tval.tv_usec = 0; if ((n = select(sockfd+1, NULL, &wset, NULL, nsec ? &tval : NULL)) == 0) { close(sockfd); /* timeout */ errno = ETIMEDOUT; return RS_ERROR1; } if (FD_ISSET(sockfd, &wset)) { len = sizeof(error); code = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len); /* 如果发生错误,Solaris实现的getsockopt返回-1, * 把pending error设置给errno. Berkeley实现的 * getsockopt返回0, pending error返回给error. * 我们需要处理这两种情况 */ if (code < 0 || error) { close(sockfd); if (error) errno = error; return RS_ERROR; } } else { fprintf(stderr, "select error: sockfd not set"); exit(0); } done: //fcntl(sockfd, F_SETFL, flags); /* restore file status flags ,这里看你自身的情况,可以选择恢复或者不恢复 */ return RS_OK; /* return 0 */ } 注:此代码是别人写的,可以拿来直接用,但是在这里连接只能保证你connect的时候是成功的,但是不能保证你后续read、write、send、recv是成功的。因此你需要在每次 read和write前检查连接是否断开。可以通过以下办法来判断(也是网上查找的资料,自己用过,是这样的): 在阻塞模式下, recv和read 一般返回0,断开。(这个待议,我没试过) 非阻塞模式下, 错误代码是EAGAIN/EWOULDBLOCK时,表示正常,未读写数据。 recv()或read()返回0时,表示断开,返回-1而errno不是EAGAIN/EWOULDBLOCK时,表示有其他错误,一般建议断开。 这里有其他的判断方法,其实和我上面说的一致。 正常断开连接情况下,判断非阻塞模式socket连接是否断开摘自:http://blog.chinaunix.net/uid-15014334-id-3429627.html 在UNIX/LINUX下, 1,对于主动关闭的SOCKET, recv返回-1,而且errno被置为9(#define EBADF 9 /* Bad file number */)或104 (#define ECONNRESET 104 /* Connection reset by peer */) 2,对于被动关闭的SOCKET,recv返回0,而且errno被置为11(#define EWOULDBLOCK EAGAIN /* Operation would block */) 3,对正常的SOCKET, 如果有接收数据,则返回>0, 否则返回-1,而且errno被置为11(#define EWOULDBLOCK EAGAIN /* Operation would block */)
因此对于简单的状态判断(不过多考虑异常情况), recv返回>0, 正常 返回-1,而且errno被置为11 正常 其它情况 关闭 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |